import ctypes
import inspect
import os
import sys
import threading
import configparser
import time
import traceback
from enum import Enum

from PyQt5 import QtCore
from PyQt5.QtCore import QObject, pyqtSignal, QEventLoop, QTimer
from PyQt5.QtWidgets import QMainWindow, QPushButton, QApplication, QTextEdit
from PyQt5.QtGui import QTextCursor, QFont


configPath = "conf/automate.conf"


class CustomEnum(Enum):
    # 全局总单量
    global orderCount
    TEST = 1
    PRO = 2
    CLUSTER = 3
    STANDALONE = 4

class CustomThread(threading.Thread): #The timer class is derived from the class threading.Thread
    def __init__(self,funcName, *args):
        threading.Thread.__init__(self)
        self.args = args
        self.funcName = funcName
        self.exitcode = 0
        self.exception = None
        self.exc_traceback = ''

    def run(self): #Overwrite run() method, put what you want the thread do here
        try:
            self._run()
        except Exception as e:
            # traceback.print_exc()
            self.exitcode = 1       # 如果线程异常退出，将该标志位设置为1，正常退出为0
            self.exception = e
            self.exc_traceback = ''.join(traceback.format_exception(*sys.exc_info()))  #在改成员变量中记录异常信息

    def _run(self):
        try:
            self.funcName(*(self.args))
        except Exception as e:
            raise e

class Stream(QObject):
    """Redirects console output to text widget."""
    newText = pyqtSignal(str)

    def write(self, text):
        self.newText.emit(str(text))


class PyWindow(QMainWindow):
    """Main application window."""

    def __init__(self):
        super().__init__()
        # Custom output stream.
        sys.stdout = Stream(newText=self.onUpdateText)
        sys.stderr = Stream(newText=self.onUpdateText)
        # 读取配置文件
        automateConf = configparser.ConfigParser()
        automateConf.read(configPath)
        self.version = automateConf.get("base", "version")
        self.curWid = automateConf.getint("base", "window_width")
        self.curHei = automateConf.getint("base", "window_height")
        self.drivers = None
        self.isClose = False
        CustomEnum.orderCount = 0
        # 禁止最大化按钮
        QMainWindow.setWindowFlags(self, QtCore.Qt.WindowCloseButtonHint | QtCore.Qt.WindowMinimizeButtonHint)
        # 禁止拉伸窗口大小
        QMainWindow.setFixedSize(self, self.curWid, self.curHei)
        self.initUI()
        # 运行自动化操作
        threading.Thread(target=self.runAutomate, args=(automateConf,)).start()

    '''异步运行 以下写启动自动化处理程序'''
    def runAutomate(self,automateConf):
        global startAutomateThread
        try:
            # automate config
            useDefaultPath = automateConf.getboolean("base", "use_default_path")
            isOpenDong = automateConf.getboolean("base", "is_open_dong")
            appSize = automateConf.getint("base", "app_size")
            basePath = automateConf.get("base", "base_path")
            dataPath = basePath + "/" + automateConf.get("base", "data_path")
            logsPath = basePath + "/" + automateConf.get("base", "logs_path")
            capturesPath = basePath + "/" + automateConf.get("base", "captures_path")
            runMode = None
            userDataPath = None
            if useDefaultPath:
                runMode = CustomEnum.STANDALONE
                userDataPath = "C:\\Users\\" + os.getlogin() + "\\AppData\\Local\\Google\\Chrome\\User Data"
            elif not useDefaultPath and appSize == 1:
                runMode = CustomEnum.STANDALONE
                userDataPath = dataPath
            elif not useDefaultPath and appSize > 1:
                runMode = CustomEnum.CLUSTER
                userDataPath = dataPath
            # 运行
            from PyNewVersion import MainAutomate
            mainAutomate = MainAutomate.MainAutomate()
            # cookies
            # mainAutomate.cookies = None
            # mainAutomate.runMode = runMode
            mainAutomate.isOpenDong = isOpenDong
            mainAutomate.logsPath = logsPath
            mainAutomate.saveLogPath = logsPath+"/errors"
            mainAutomate.capturesPath = capturesPath
            userDataPaths = {}
            print("start run mode is  "+str(runMode.name))
            if runMode is CustomEnum.CLUSTER:
                for i in range(appSize):
                    index = i + 1
                    userDataPathTemp = userDataPath+str(index)
                    userDataPaths[index] = userDataPathTemp
                    mainAutomate.newChrome(userDataPathTemp,index)
                    self.drivers = mainAutomate.drivers
                    if self.isClose:
                        return
            else:
                index = 1000
                userDataPaths[index] = userDataPath
                mainAutomate.newChrome(userDataPath,index)
                self.drivers = mainAutomate.drivers
                if self.isClose:
                    return
            threads = {}
            for index in mainAutomate.drivers.keys():
                startAutomateThread = CustomThread(mainAutomate.startAutomate,mainAutomate.drivers[index])
                # threading.Thread(target=mainAutomate.startAutomate,args=(driver,)).start()
                threads[index] = startAutomateThread
                startAutomateThread.start()
            while True:
                if self.isClose:
                    return
                for index in threads.keys():
                    thread = threads[index]
                    if thread.exitcode == 1:
                        mainAutomate.newChrome(userDataPaths[index],index)
                        self.drivers[index] = mainAutomate.drivers[index]
                        threads[index] = CustomThread(mainAutomate.startAutomate,mainAutomate.drivers[index])
                        threads[index].start()
        except Exception:
            import traceback
            traceback.print_exc()

    def onUpdateText(self, text):
        """Write console output to text widget."""
        cursor = self.process.textCursor()
        cursor.movePosition(QTextCursor.End)
        cursor.insertText(text)
        self.process.setTextCursor(cursor)
        self.process.ensureCursorVisible()

    def closeEvent(self, event):
        self.isClose = True
        sys.stdout = sys.__stdout__
        # 退出应用程序
        if self.drivers is not None:
            for index in self.drivers:
                self.drivers[index].quit()
        os.system('taskkill /F /IM chromedriver.exe')
        os._exit()

    def initUI(self):
        # Set window size and title, then show the window.
        desktop = QApplication.desktop()
        pos_x = (desktop.width() - self.curWid) / 2
        pos_y = (desktop.height() - self.curHei) / 2
        # Create the text output widget.
        self.process = QTextEdit(self, readOnly=True)
        self.process.setHtml("<font color='black' size='6'>欢迎使用自动化插件，</font>")
        print("启动" + self.version + "版本 ！")
        self.process.ensureCursorVisible()
        # self.process.setLineWrapColumnOrWidth(500)
        # self.process.setLineWrapMode(QTextEdit.FixedPixelWidth)
        self.process.setFixedWidth(self.curWid)
        self.process.setFixedHeight(self.curHei)
        self.process.setFontPointSize(100)
        self.setGeometry(int(pos_x), int(pos_y), self.curWid, self.curHei)
        self.setWindowTitle('自动化插件' + self.version)
        self.show()


if __name__ == '__main__':
    # Run the application.
    app = QApplication(sys.argv)
    # app.aboutToQuit.connect(app.deleteLater)
    gui = PyWindow()
    sys.exit(app.exec_())
